home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / PROGTOOL / LIB211.ZIP;1 / WINDOWS.PRG < prev    next >
Encoding:
Text File  |  1993-11-22  |  65.0 KB  |  1,678 lines

  1. *-----------------------------------------------------------------------
  2. *-- Program...: WINDOWS.PRG
  3. *-- Programmer: Ken Mayer (CIS: 71333,1030)
  4. *-- Date......: 07/27/1993
  5. *-- Notes.....: This original set of functions was published in the 
  6. *--             JUNE, 1992 issue of Technotes for dBASE IV (Vol. 90). 
  7. *--             The routines were created by Adam Menkes (Borland), 
  8. *--             except for the ones added in (used by a couple of the 
  9. *--             functions) that were written by Jay Parsons and others.
  10. *--             For a complete explanation on how these routines work, 
  11. *--             you need to read the article in TechNotes. 
  12. *--             Some of these routines inspired others in DIALOGS.PRG
  13. *--             and PROC.PRG.
  14. *-----------------------------------------------------------------------
  15.  
  16. FUNCTION Alert
  17. *-----------------------------------------------------------------------
  18. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  19. *-- Date........: 06/01/1992
  20. *-- Notes.......: This routine creates a popup on the screen with a 
  21. *--               title and one line message, forcing the user to notice
  22. *--               the message. The user must use the mouse on the 'OK' 
  23. *--               pad, press <Esc> or press <Enter> to move on in the 
  24. *--               program that called this function.
  25. *-- Written for.: dBASE IV, 1.5
  26. *-- Rev. History: 06/01/1992 - Original
  27. *--               06/19/1992 - Modified to accept the <Enter> key by
  28. *--                  Ken Mayer, also a bit better cleanup at the end 
  29. *--                  (releasing things from memory, and so on).
  30. *-- Calls.......: None
  31. *-- Called by...: Any
  32. *-- Usage.......: Alert("<cTitle>","<cMessage>")
  33. *-- Example.....: lX = Alert("Print Aborted","You pressed <ESC>")
  34. *-- Returns.....: Logical
  35. *-- Parameters..: cTitle   = Title line
  36. *--               cMessage = One line message (up to 79 characters)
  37. *-----------------------------------------------------------------------
  38.  
  39.    parameters cTitle, cMessage
  40.    private wWindow,nRow,nCol,mPad
  41.    
  42.    m->wWindow = WINDOW()               && save current Window
  43.    save screen to sTemp                && save the screen
  44.    activate screen
  45.    
  46.    m->nRow = iif(val(right(set("DISPLAY"),2)) = 43,18,8)  
  47.      && center from top to bottom (does not take VGA50 into account)
  48.                          
  49.    m->nCol = 38 - (max(len(m->cTitle),len(m->cMessage))/2)
  50.                                                     && center left/rt
  51.    m->nCol2 = max(len(m->cTitle),len(m->cMessage))  && right side?
  52.    
  53.    *-- clear out a section of the screen
  54.    @m->nRow,m->nCol Clear to m->nRow+6,m->nCol+m->nCol2
  55.    *-- fill in a box
  56.    @m->nRow,m->nCol Fill  to m->nRow+6,m->nCol+m->nCol2+1 color n+  
  57.                                                                  && grey
  58.    *-- put a double line border around box
  59.    @m->nRow,m->nCol to m->nRow+6,m->nCol+m->nCol2+1 double color bg+
  60.    *-- display title
  61.    @m->nRow + 1,m->nCol + 1 + iif(len(m->cTitle) > len(m->cMessage),0,;
  62.       (len(m->cMessage)-len(m->cTitle)) / 2) say m->cTitle color w+/n
  63.    *-- display line 
  64.    @m->nRow + 2, m->nCol + 1 to m->nRow + 2, m->nCol + m->nCol2 color bg+
  65.    *-- display message
  66.    @m->nRow + 3, m->nCol+1+iif(len(m->cTitle) > len(m->cMessage),;
  67.        (len(m->cTitle)-len(m->cMessage)) / 2, 0) say m->cMessage ;
  68.        color w+/n
  69.    
  70.    *-- define/display a very small menu (one pad)
  71.    define menu mAlert
  72.    define pad pPad1 of mAlert prompt " OK " at m->nRow +5,37
  73.    on selection pad pPad1 of mAlert deactivate menu
  74.    
  75.    *-- added by Ken to deal with <Enter>
  76.    on key label ctrl-M keyboard "{27}"
  77.    
  78.    *-- start it up
  79.    activate menu mAlert
  80.    
  81.    *-- deal with user 'input'
  82.    m->mPad = pad()
  83.    
  84.    *-- restore environment, free up RAM by releasing things
  85.    on key label ctrl-m
  86.    restore screen from sTemp
  87.    release screen sTemp
  88.    release menu mAlert
  89.    if "" # m->wWindow
  90.    activate window &wWindow.
  91.    endif
  92.    
  93. RETURN .not. "" = m->mPad  && not empty pad?
  94. *-- EoF: Alert()
  95.  
  96. FUNCTION CheckBox
  97. *-----------------------------------------------------------------------
  98. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  99. *-- Date........: 06/01/1992
  100. *-- Notes.......: This routine brings up a one-line message, allows the 
  101. *--               user to click mouse/press <Space> on it, to change 
  102. *--               status. Pressing <Enter>/<Esc> chooses the current 
  103. *--               setting ...
  104. *-- Written for.: dBASE IV, 1.5
  105. *-- Rev. History: 06/01/1992 -- Original Release
  106. *-- Calls.......: None
  107. *-- Called by...: Any
  108. *-- Usage.......: CheckBox(<lVar>,"<cTitle>",<m->nRow>,<nCol>,<nASCII>)
  109. *-- Example.....: lX = CheckBox(.t.,"OK as is?",9,10,4)
  110. *-- Returns.....: Logical
  111. *-- Parameters..: lVar     = On or Off to start? (.t.=on, .f.=off)
  112. *--               cTitle   = Title/Message
  113. *--               nRow     = Row to place this
  114. *--               nCol     = Column ...
  115. *--               nASCII   = ascii character to use in box. (Optional)
  116. *--                          Default is 251 (˚). Other suggestions 
  117. *--                          include:
  118. *--                          4 (diamond), 176 (∞), 177 (±), 178 (≤),
  119. *--                          219 (€), 249 (˘), 250 (˙), 254 (˛)
  120. *--                          (Check out the ASCII chart in the language 
  121. *--                           reference)
  122. *-----------------------------------------------------------------------
  123.  
  124.    parameters lVar, cTitle, nRow, nCol, nASCII
  125.    
  126.    *-- if parameter is left blank, assign 251 (˚)
  127.    m->nASCII = iif(pCount() = 5, m->nASCII, 251)
  128.    
  129.    define menu mCheck
  130.    
  131.    *-- loop until user does something, or presses <Esc>
  132.    do while .t.
  133.    
  134.       *-- define the menu pad ...
  135.       define pad pCheck1 of mCheck at m->nRow,m->nCol prompt;
  136.          "["+iif(m->lVar,chr(m->nASCII)," ")+"] "+m->cTitle
  137.       on selection pad pCheck1 of mCheck deactivate menu
  138.    
  139.       *-- when user presses <Enter> turn it all off ... (send <Esc> ...)
  140.       on key label ctrl-m keyboard "{27}"
  141.    
  142.       *-- start 'er up
  143.       activate menu mCheck
  144.    
  145.       *-- (<Esc> or <Enter>)
  146.       if lastkey() = 27
  147.          exit
  148.       endif
  149.    
  150.       m->lVar = .not. m->lVar   && set to opposite of current setting
  151.    
  152.    enddo
  153.    
  154.    *-- reset environment/release things
  155.    on key label ctrl-m
  156.    release menu mCheck
  157.  
  158. RETURN m->lVar
  159. *-- EoF: CheckBox()
  160.  
  161. Function CheckBx1
  162. *-----------------------------------------------------------------------
  163. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  164. *-- Date........: 06/01/1992
  165. *-- Notes.......: This routine brings up a one-line message, allows the 
  166. *--               user to click mouse/press <Space> on it, to change 
  167. *--               status. Pressing <Enter>/<Esc> chooses the current 
  168. *--               setting ... This one is different, in that it does 
  169. *--               not use a menu to accomplish it's ends, but uses 
  170. *--               instead a memvar, with @/GET/READ and a picture 
  171. *--               using the multiple choice ("@M") function.
  172. *-- Written for.: dBASE IV, 1.5
  173. *-- Rev. History: 06/01/1992 -- Original
  174. *-- Calls.......: None
  175. *-- Called by...: Any
  176. *-- Usage.......: CheckBx1(<lVar>,"<cTitle>",<m->nRow>,<nCol>)
  177. *-- Example.....: lX = CheckBx1(.t.,"OK as is?",9,10)
  178. *-- Returns.....: Logical
  179. *-- Parameters..: lVar     = On or Off to start? (.t.=on, .f.=off)
  180. *--               cTitle   = Title/Message
  181. *--               nRow     = Row to place this
  182. *--               nCol     = Column ...
  183. *-----------------------------------------------------------------------
  184.  
  185.    parameters lVar, cTitle, nRow, nCol
  186.    
  187.    *-- save parts of environment ...
  188.    m->cFormat = set("FORMAT")
  189.    set format to
  190.    m->cCursor = set("CURSOR")
  191.    set cursor off
  192.    
  193.    *-- define starting value of cVar ... 
  194.    *-- (this is ASCII 255, ˚, ASCII 255, if lVar = .t., 3 spaces 
  195.    *-- if lVar = .f.)
  196.    m->cVar = iif(m->lVar,chr(255)+chr(251)+chr(255),space(3))
  197.    
  198.    *-- display/get, using picture
  199.    @m->nRow,m->nCol get m->cVar picture "@M ,ˇ˚ˇ"
  200.    *-- this picture is: space, comma, chr(255), chr(251), chr(255).
  201.    @m->nRow,m->nCol + 4 say m->cTitle
  202.    
  203.    READ
  204.    
  205.    *-- reset environment
  206.    set format to &cFormat.
  207.    set cursor &cCursor.
  208.    
  209. RETURN .not. (m->cVar = chr(32))   && not a space
  210. *-- EoF: CheckBx1()
  211.  
  212. FUNCTION DropDown
  213. *-----------------------------------------------------------------------
  214. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  215. *-- Date........: 06/01/1992
  216. *-- Notes.......: This function performs a picklist of a different sort.
  217. *--               In order to use it, you will either use an ARRAY (one-
  218. *--               dim) or a field in a database. It holds a choice in a 
  219. *--               'holding area', allowing the user to leave it there, 
  220. *--               and maybe to change it with another option in the 
  221. *--               list.
  222. *--
  223. *--               I recommend you display an on-screen message for this 
  224. *--               one, because it's not real intuitive (at least not to 
  225. *--               me). To bring up the list, click on the arrows, to 
  226. *--               select an item, click on the item, or highlight and 
  227. *--               press <enter>. To Change, click (or select) another 
  228. *--               item. To choose the actual item you want, click on 
  229. *--               the one NEXT to the arrows (or use the arrow keys 
  230. *--               to select that menu pad, and press <Enter>).
  231. *-- Written for.: dBASE IV, 1.5
  232. *-- Rev. History: 06/01/1992 -- Original
  233. *-- Calls.......: TEMPNAME()           Function in WINDOWS.PRG
  234. *--               ARRAYROWS()          Function in WINDOWS.PRG
  235. *--               ARRAYCOLS()          Function in WINDOWS.PRG
  236. *--               FIELDNUM()           Function in WINDOWS.PRG
  237. *-- Called by...: Any
  238. *-- Usage.......: DropDown("<cType>","<cName>",[<nRow>,[<nCol>,;
  239. *--                                            [<nSize>]]])
  240. *-- Example.....: x=DropDown("F","Lastname",10,15,6)
  241. *--
  242. *--               Here is a suggested use:
  243. *--               @5,10 get cName when calldrop()  && function below
  244. *--               read
  245. *--               *-- do other stuff
  246. *--               FUNCTION CallDrop
  247. *--                 *-- display message about how to use
  248. *--                 @18,10 say "<Enter> or Click mouse on "+chr(23)+;
  249. *--                                         " to see list"
  250. *--                 @19,10 say "<Enter> or Click mouse on name at top"+;
  251. *--                             " to select"
  252. *--                 *-- call it ... if using a FIELD in the database, 
  253. *--                 *-- you might want to use a temp var, and then 
  254. *--                 *-- REPLACE <field> WITH ...
  255. *--                 cName = dropdown("F","NAME",6,10,5)  
  256. *--                                        && call dropdown func.
  257. *--                 *-- redisplay it and clean out the 'gets' from 
  258. *--                 *-- memory
  259. *--                 @5,10 get cName
  260. *--                 clear gets
  261. *--                 keyboard chr(23)  && move on to next field ...
  262. *--               RETURN .T.
  263. *-- Returns.....: Selected item
  264. *-- Parameters..: cType  = 'F' = Field, 'A' = Array (1-Dimensional)
  265. *--               cName  = Field or Array name
  266. *--               nRow   = Coordinates to display menu
  267. *--               nCol   = Same  
  268. *--               nSize  = Number of items to display below dropdown 
  269. *--                        box
  270. *-----------------------------------------------------------------------
  271.  
  272.    parameters cType, cName, nRow, nCol, nSize
  273.    
  274.    *-- If these optional parms are NOT passed, we need to set default
  275.    *-- values ...
  276.    m->nSize = iif(pcount() <= 4, 5, m->nSize)
  277.    m->nCol  = iif(pCount() <= 3,10, m->nCol)
  278.    m->nRow  = iif(pCount() <= 2, 5, m->nRow)
  279.    
  280.    *-- setup
  281.    m->nMaxLen = 1
  282.    m->lNone = (set("BORDER") = "NONE")
  283.    define menu mDropDown
  284.    
  285.    *-- if it's an array, we work here for setup ...
  286.    if upper(m->cType) = "A"
  287.       m->nCols = arraycols(m->cName)
  288.       m->nRows = arrayrows(m->cName)
  289.       *-- determine width of display, by scanning each element of
  290.       *-- array and finding the largest ...
  291.       m->nX = 1
  292.       do while m->nX <= m->nCols
  293.          m->nMaxLen = Max(m->nMaxLen, len(&cName.[m->nX]))
  294.          m->nX = m->nX + 1
  295.       enddo
  296.    
  297.       *-- here we're gonna define the popup part of it ...
  298.       define popup pDropDown from m->nRow+iif(m->lNone,0,1),;
  299.          m->nCol-iif(m->lNone,1,0) to m->nRow+m->nSize+;
  300.          iif(m->lNone,1,2),m->nCol+m->nMaxLen+iif(m->lNone,0,1)
  301.       *-- define the bars ... the loops have to be done seperate,
  302.       *-- since the width must be determined before the bars are defined.
  303.       m->nX = 1
  304.       do while m->nX <= m->nCols
  305.          define bar m->nX of DropDown prompt &cName.[m->nX]
  306.          m->nX = m->nX + 1
  307.       enddo
  308.    
  309.    else
  310.       *-- process if it's a field here
  311.       do case
  312.          case type ("&cName.") = "C"  && character
  313.             calculate max(len(trim(&cName.))) to m->nMaxLen
  314.          case type ("&cName.") $ "FN" && numeric (or floating)
  315.             cAlias = alias()
  316.             dbftemp = tempname("DBF")
  317.             nNum = fieldnum(m->cName)
  318.             copy structure extended to (dbfTemp)
  319.             select select()
  320.             use (dbftemp) exclusive nosave
  321.             go nNum
  322.             m->nMaxLen = field_Len
  323.             use
  324.             select (cAlias)
  325.          case type ("&cName.") = "D"
  326.             m->nMaxLen = iif(set("CENTURY") = "ON",10,8)
  327.          case type ("&cName.") = "L"
  328.             m->nMaxLen = 1
  329.       endcase
  330.       define popup pDropdown from m->nRow + iif(m->lNone,0,1),;
  331.            m->nCol-iif(m->lNone,1,0) to;
  332.            m->nRow+m->nSize+iif(m->lNone,1,2),;
  333.            m->nCol+m->nMaxLen+iif(m->lNone,0,1) prompt field &cName.
  334.    endif
  335.    
  336.    *-- define the pad that activates this thing ...
  337.    define pad pPad2 of mDropDown prompt chr(23) at m->nRow,;
  338.                                          m->nCol+m->nMaxLen
  339.    on selection pad pPad2 of mDropDown activate popup pDropDown
  340.    on selection popup pDropDown deactivate menu
  341.    
  342.    do while lastkey() # 27
  343.       m->xPrompt = trim(prompt())+space(m->nMaxLen - ;
  344.                                          len(trim(prompt())))
  345.       define pad pPad1 of mDropDown prompt m->xPrompt at m->nRow,;
  346.                                                       m->nCol
  347.       on selection pad pPad1 of mDropDown deactivate menu
  348.       activate menu mDropDown pad pPad2
  349.       if pad() = "PPAD1"
  350.          exit
  351.       endif
  352.    enddo
  353.    
  354.    release popup pDropDown
  355.    release menu mDropDown
  356.    
  357. RETURN trim(prompt())
  358. *-- EoF: DropDown()
  359.  
  360. FUNCTION MsWind
  361. *-----------------------------------------------------------------------
  362. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  363. *-- Date........: 06/01/1992
  364. *-- Notes.......: This one creates a window that acts like one from 
  365. *--               WINDOWS, in that you can move it, enlarge it to full-
  366. *--               screen, and bring it back to its original size.
  367. *-- Written for.: dBASE IV, 1.5
  368. *-- Rev. History: 06/01/1992 -- Original
  369. *-- Calls.......: MOVEWINU             Procedure in WINDOWS.PRG
  370. *--               MOVEWIND             Procedure in WINDOWS.PRG
  371. *--               ENLARGE              Procedure in WINDOWS.PRG
  372. *--               MSWINACT             Procedure in WINDOWS.PRG
  373. *-- Called by...: Any
  374. *-- Usage.......: MsWind(<nTop>,<nLeft>,<nLower>,<nRight>)
  375. *-- Example.....: x=MsWind(5,10,20,70)
  376. *-- Returns.....: Logical
  377. *-- Parameters..: nTop    = Top Row of window
  378. *--               nLeft   = Left column
  379. *--               nBottom = Bottom Row of Window
  380. *--               nRight  = Right column
  381. *-----------------------------------------------------------------------
  382.  
  383.    parameters nTop, nLeft, nLower, nRight
  384.    
  385.    *-- save environment
  386.    save screen to sMSWIND
  387.    m->lStatus = (set("STATUS") = "ON")
  388.    m->lDisp43 = ("43" $ SET("DISPLAY"))
  389.    
  390.    *-- loop
  391.    do while .t.
  392.       restore screen from sMSWIND
  393.    
  394.       *-- define/redefine window area and box
  395.       @m->nTop, m->nLeft clear to m->nLower, m->nRight
  396.       @m->nTop, m->nLeft TO m->nLower, m->nRight
  397.    
  398.       *-- using menus to simulate Windows window ...
  399.       define menu wNormal
  400.       define pad pCabinet of wNormal prompt "["+chr(254)+"]";
  401.              at m->nTop, m->nLeft + 1           && ˛
  402.       define pad pMoveUp  of wNormal prompt chr(18) ;
  403.              at m->nTop, m->nRight - 4          && up/down-arrow
  404.       define pad pEnlarge of wNormal prompt chr(30) ;
  405.              at m->nTop, m->nRight - 1          && up-arrow-head
  406.       define pad pMoveDn  of wNormal prompt chr(18) ;
  407.              at m->nLower, m->nRight - 4        && up/down arrow again
  408.    
  409.       *-- tell it what to do when an item is selected
  410.       on selection pad pCabinet of wNormal deactivate menu
  411.       on selection pad pMoveUp  of wNormal do movewinu
  412.       on selection pad pEnlarge of wNormal do enlarge
  413.       on selection pad pMoveDn  of wNormal do movewind
  414.    
  415.       *-- deal with changes ...
  416.       do mswinact with m->nTop, m->nLeft
  417.       activate menu wnormal
  418.       *-- User pressed <Esc> or chose the 'close window' button/pad
  419.       if lastkey() = 27 .or. "PCABINET" = pad()
  420.          exit
  421.       endif
  422.    
  423.    enddo  && end of loop
  424.    
  425.    *-- restore environment
  426.    restore screen from sMSWIND
  427.    release screen sMSWIND
  428.    release menu wNormal
  429.  
  430. RETURN .not. "" = pad()
  431. *-- EoF: MSWind()
  432.  
  433. PROCEDURE Enlarge
  434. *-----------------------------------------------------------------------
  435. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  436. *-- Date........: 06/01/1992
  437. *-- Notes.......: Used in MSWIND() to 'enlarge' the window, and 
  438. *--               redefine the menu ...
  439. *-- Written for.: dBASE IV, 1.5
  440. *-- Rev. History: 06/01/1992 -- Original
  441. *-- Calls.......: MsWinAct             Procedure in WINDOWS.PRG
  442. *-- Called by...: MsWind()             Function in WINDOWS.PRG
  443. *-- Usage.......: Do Enlarge
  444. *-- Example.....: Do Enlarge
  445. *-- Returns.....: None
  446. *-- Parameters..: None
  447. *-----------------------------------------------------------------------
  448.    
  449.    *-- clear screen, draw border from upper left to a bottom 
  450.    *-- right corner ...
  451.    clear
  452.    @0,0 to iif(m->lStatus,21,24) + iif(m->lDisp43,18,0), 79
  453.    
  454.    *-- define new version of menu
  455.    define menu mEnlarge
  456.    define pad pCabinet of mEnlarge prompt "["+chr(254)+"]" at 0,2
  457.    define pad pReduce  of mEnlarge prompt chr(31) at 0,78
  458.    on selection pad pCabinet of mEnlarge deactivate menu
  459.    on selection pad pReduce  of mEnlarge deactivate menu
  460.    
  461.    *-- Routine to allow interaction inside menu window ...
  462.    do mswinact with 0,0
  463.  
  464.    *-- start 'er up
  465.    activate menu mEnlarge
  466.    deactivate menu
  467.    if lastkey() = 27
  468.       keyboard "{27}"
  469.    endif
  470.    release menu mEnlarge
  471.    clear
  472.  
  473. RETURN
  474. *-- EoP: Enlarge
  475.  
  476. PROCEDURE MoveWinU
  477. *-----------------------------------------------------------------------
  478. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  479. *-- Date........: 06/01/1992
  480. *-- Notes.......: Used in MSWIND() to move the window up (unless the
  481. *--               window is at the top of the screen ...)
  482. *-- Written for.: dBASE IV, 1.5
  483. *-- Rev. History: 06/01/1992 -- Original
  484. *-- Calls.......: None
  485. *-- Called by...: MsWind()             Function in WINDOWS.PRG
  486. *-- Usage.......: Do MoveWinU
  487. *-- Example.....: Do MoveWinU
  488. *-- Returns.....: None
  489. *-- Parameters..: None
  490. *-----------------------------------------------------------------------
  491.    
  492.    *-- check for top of screen ... change coordinates
  493.    m->nTop = m->nTop - iif(m->nTop = 0,0,1)
  494.    m->nLower = m->nLower - iif(m->nTop = 0,0,1)
  495.    deactivate menu
  496.  
  497. RETURN
  498. *-- EoP: MoveWinU
  499.  
  500. PROCEDURE MoveWinD
  501. *-----------------------------------------------------------------------
  502. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  503. *-- Date........: 06/01/1992
  504. *-- Notes.......: Used in MSWIND() to move the window down (unless the
  505. *--               window is at the bottom of the screen ...)
  506. *-- Written for.: dBASE IV, 1.5
  507. *-- Rev. History: 06/01/1992 -- Original
  508. *-- Calls.......: None
  509. *-- Called by...: MsWind()             Function in WINDOWS.PRG
  510. *-- Usage.......: Do MoveWinD
  511. *-- Example.....: Do MoveWinD
  512. *-- Returns.....: None
  513. *-- Parameters..: None
  514. *-----------------------------------------------------------------------
  515.    
  516.    *-- check for bottom of screen/status line ... change coordinates
  517.    m->nTop = m->nTop + iif(m->nLower = iif(m->lStatus,21,24)+;
  518.       iif(m->lDisp43,18,0),0,1)
  519.    m->nLower = m->nLower + iif(m->nLower=iif(m->lStatus,21,24)+;
  520.       iif(m->lDisp43,18,0),0,1)
  521.    deactivate menu
  522.  
  523. RETURN
  524. *-- EoP: MoveWinD
  525.  
  526. PROCEDURE MSWinAct
  527. *-----------------------------------------------------------------------
  528. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  529. *-- Date........: 06/01/1992
  530. *-- Notes.......: Used in MSWIND() to move the actually display/
  531. *--               redisplay information inside the window, even when a 
  532. *--               window has been moved. This routine should be modified
  533. *--               for a specific system ... 
  534. *-- Written for.: dBASE IV, 1.5
  535. *-- Rev. History: 06/01/1992 -- Original
  536. *-- Calls.......: None
  537. *-- Called by...: MsWind()             Function in WINDOWS.PRG
  538. *-- Usage.......: Do MSWinAct with <nTop>, <nLeft>
  539. *-- Example.....: Do MSWinAct with 5,10
  540. *-- Returns.....: None
  541. *-- Parameters..: None
  542. *-----------------------------------------------------------------------
  543.    
  544.    parameters nTop, nLeft
  545.    private nTop, nLeft
  546.    
  547.    @m->nTop + 2, m->nLeft + 2 say "This is line 1"
  548.    @m->nTop + 3, m->nLeft + 2 say "And this is line 2"
  549.    
  550. RETURN
  551. *-- EoP: MSWinAct
  552.  
  553. FUNCTION RadioBut
  554. *-----------------------------------------------------------------------
  555. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  556. *-- Date........: 06/01/1992
  557. *-- Notes.......: This is a Radio Button routine.  NOTE that the array 
  558. *--               called as cArray below must be a character array 
  559. *--               (i.e., all data must be character data ...).
  560. *-- Written for.: dBASE IV, 1.5
  561. *-- Rev. History: 06/01/1992 -- Original
  562. *-- Calls.......: ArrayRows()          Function in WINDOWS.PRG
  563. *--               TmpRadio             Procedure in WINDOWS.PRG
  564. *-- Called by...: None
  565. *-- Usage.......: RadioBut("<cArray>",<nRow>,<nCol>,<nDefPad>,<nASCII>)
  566. *-- Example.....: nReturn =  RadioBut("aTest",5,10,1,15)
  567. *-- Returns.....: Numeric (Array Index of item selected)
  568. *-- Parameters..: cArray  = Name of Array (Character data)
  569. *--               nRow    = Row for coordinates ... (start position)
  570. *--               nCol    = Column for same
  571. *--               nDefPad = Default Pad number
  572. *--               nASCII  = ASCII character to use as 'button'(Optional)
  573. *--                   try: 4 (Diamond), 9 (Circle), 15 (splot), 42 (*), 
  574. *--                        249 (˘), 251 (˚) or 254 (˛) ...
  575. *-----------------------------------------------------------------------
  576.    
  577.    parameters cArray, nRow, nCol, nDefPad, nASCII
  578.    
  579.    define menu mRadio
  580.    public aTmpRadio, nARows, nPad
  581.    
  582.    *-- get number of items to display
  583.    m->nARows = ArrayRows(m->cArray)
  584.    
  585.    *-- set character for 'button'
  586.    m->nASCII = iif(PCOUNT() <= 4,4,m->nASCII) && default is a 'diamond'
  587.    
  588.    *-- start definitions ...
  589.    m->cPad = iif(pcount() => 4 .and. m->nDefPad # 0,;
  590.              ltrim(str(m->nDefPad)),"1")
  591.    m->nCol = iif(pcount() <= 2,10,m->nCol)
  592.    m->nRow = iif(pCount() <= 1,5,m->nRow)
  593.    
  594.    *-- here we get the largest item in the array ...
  595.    m->nX = 1
  596.    m->nLongest = 1
  597.    do while m->nX <= m->nARows
  598.       m->nLongest = max(m->nLongest,len(trim(&cArray.[m->nX])))
  599.       m->nX = m->nX + 1
  600.    enddo
  601.    
  602.    *-- define a temporary array ...
  603.    declare aTmpRadio[m->nARows]
  604.    
  605.    on key label ctrl-m keyboard "{27}"  && close down if <Enter> ...
  606.    
  607.    m->cX = "1"
  608.    do while .t.
  609.    
  610.       *-- define menu pads
  611.       do while val(m->cX) <= m->nARows
  612.          define pad button&cX. of mRadio at m->nRow - 1 + val(m->cX),;
  613.                  m->nCol prompt "("+ iif(aTmpRadio[val(m->cX)] ;
  614.                 .or. m->cPad = m->cX,chr(m->nASCII)," ")+") "+;
  615.                 trim(&cArray.[val(m->cX)])+;
  616.                 space(m->nLongest-len(trim(&cArray.[val(m->cX)])))
  617.          on selection pad button&cX. of mRadio deactivate menu
  618.          m->cX = ltrim(str(val(m->cX)+1))
  619.       enddo
  620.    
  621.       *-- start 'er up
  622.       activate menu mRadio pad button&nPad.
  623.       *-- if <Esc> (or <Enter>), we're done ...
  624.       if lastkey() = 27
  625.          nPad = substr(pad(),7)
  626.          exit
  627.       else
  628.          *-- if not, perform routine below to reset the temp array ...
  629.          do TmpRadio
  630.       endif
  631.    enddo
  632.    
  633.    *-- cleanup
  634.    on key label ctrl-m
  635.    m->nY = 1
  636.    do while m->nY <= m->nARows .and. .not. aTmpRadio[m->nY]
  637.       m->nY = m->nY + 1
  638.    enddo
  639.    release aTmpRadio, nPad
  640.    release menu mRadio
  641.  
  642. RETURN iif(m->nY > m->nARows, 0, m->nY)
  643. *-- EoF: RadioBut()
  644.  
  645. PROCEDURE TmpRadio
  646. *-----------------------------------------------------------------------
  647. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  648. *-- Date........: 06/01/1992
  649. *-- Notes.......: Used to set/reset the temporary array aTmpRadio[] for 
  650. *--               use in the RadioBut() function above.
  651. *-- Written for.: dBASE IV, 1.5
  652. *-- Rev. History: 06/01/1992 -- Original
  653. *-- Calls.......: None
  654. *-- Called by...: RadioBut()           Function in WINDOWS.PRG
  655. *-- Usage.......: Do TmpRadio
  656. *-- Example.....: Do TmpRadio
  657. *-- Returns.....: None
  658. *-- Parameters..: None
  659. *-----------------------------------------------------------------------
  660.    
  661.    m->nPad = substr(pad(),7)
  662.    m->nY = 1
  663.    do while m->nY <= m->nARows
  664.       aTmpRadio[m->nY] = .f.
  665.       m->nY = m->nY + 1
  666.    enddo
  667.    aTmpRadio[val(m->nPad)] = .t.
  668.    m->cX = "1"
  669.  
  670. RETURN
  671. *-- EoP: TmpRadio
  672.  
  673. FUNCTION ScrolBar
  674. *-----------------------------------------------------------------------
  675. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  676. *-- Date........: 06/01/1992
  677. *-- Notes.......: Performs a horizontal scroll-bar to find a record in a 
  678. *--               database file. Note that this function assumes a 
  679. *--               database is open. Not quite sure how I'd use this one 
  680. *--               ...
  681. *-- Written for.: dBASE IV, 1.5
  682. *-- Rev. History: 06/01/1992 -- Original
  683. *-- Calls.......: None
  684. *-- Called by...: None
  685. *-- Usage.......: ScrolBar(<nAtLine>)
  686. *-- Example.....: This example is from the text of Adam's article:
  687. *--               Add the following line to your program or FMT file:
  688. *--
  689. *--               ON KEY LABEL F5 DO MoveRec
  690. *--
  691. *--               Create a simple PROCEDURE or program with the 
  692. *--               following:
  693. *--
  694. *--               PROCEDURE MoveRec
  695. *--                 on key label ctrl-M chr(27) && press <Enter> 
  696. *--                 x=scrolbar(20)              && call function
  697. *--                 on key label ctrl-M         && reset CTRL-M key
  698. *--               RETURN
  699. *--
  700. *-- Returns.....: .T.
  701. *-- Parameters..: nAtLine = Line of screen (ROW) to display scroll bar 
  702. *--                         at.
  703. *-----------------------------------------------------------------------
  704.    
  705.    parameters nAtLine
  706.    m->nAtLine = iif(pCount() = 1, m->nAtLine, 20)
  707.    m->nBreak = 76
  708.    m->cX = "1"
  709.    m->nY = 1
  710.    m->nRecord = reccount()
  711.    m->nZ = (m->nBreak/m->nRecord) - int(m->nBreak/m->nRecord)
  712.    
  713.    *-- once again, this is being done via a menu ...
  714.    define menu mScrollBar 
  715.    define pad pPad0 of mScrollBar prompt chr(17) at m->nAtLine, 1
  716.    *-- if the first pad is selected, back up one record
  717.    on selection pad pPad0 of mScrollBar skip iif(bof(),0,-1)
  718.    
  719.    *-- deal with location of the rest ...
  720.    do while val(m->cX) <= m->nRecord
  721.       if m->nRecord <= m->nBreak
  722.          define pad pPad&cX. of mScrollBar ;
  723.             prompt;
  724.             space((m->nBreak/m->nRecord)+iif(m->nZ => 1, int(m->nZ),0));
  725.                at m->nAtLine, m->nY + 1
  726.       endif
  727.       m->nY = m->nY + int(m->nBreak/m->nRecord)+iif(m->nZ => 1, ;
  728.                                                 int(m->nZ),0)
  729.       if m->nZ => 1
  730.          m->nZ = m->nZ - int(m->nZ)
  731.       endif
  732.    
  733.       m->nZ = m->nZ + (m->nBreak / m->nRecord) - ;
  734.                       int(m->nBreak/m->nRecord)
  735.       on selection pad pPad&cX. of mScrollBar go val(substr(pad(),4))
  736.       m->cX = ltrim(str(val(m->cX) + 1))
  737.    enddo
  738.    
  739.    *-- define final pad
  740.    define pad pPad&cX. of mScrollBar prompt chr(16) at m->nAtLine, ;
  741.                                                        m->nY + 1
  742.    on selection pad pPad&cX. of mScrollBar skip iif(eof(),0,1)
  743.    
  744.    *-- start 'er up ...
  745.    activate menu mScrollBar
  746.  
  747. RETURN .t.
  748. *-- EoF: ScrolBar()
  749.  
  750. *-----------------------------------------------------------------------
  751. *-- This section is where I (Ken Mayer) attempted to modify/improve some
  752. *-- of Adam's routines ... I may or may not have been successful, 
  753. *-- YOU decide ... <g>
  754. *-----------------------------------------------------------------------
  755.  
  756. FUNCTION Alert2
  757. *-----------------------------------------------------------------------
  758. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  759. *-- Date........: 11/09/1992
  760. *-- Notes.......: This routine creates a popup on the screen with a 
  761. *--               title and one line message, forcing the user to notice
  762. *--               the message. The user must use the mouse on the 'OK' 
  763. *--               pad, press <Esc> or press <Enter> to move on in the 
  764. *--               program that called this function.
  765. *-- Written for.: dBASE IV, 1.5
  766. *-- Rev. History: 06/19/1992 -- Modified to accept the <Enter> key by 
  767. *--                     Ken Mayer.
  768. *--               06/19/1992 -- Copied from Adam's original, uses a 
  769. *--                     window, shadow, and programmer defineable 
  770. *--                     colors.
  771. *--               07/29/1992 -- Joey stepped in and made some 
  772. *--                     modifications that seem to have helped as well,
  773. *--                     including dealing with the keyboard buffer.
  774. *--               10/09/1992 -- minor change -- title is now same color 
  775. *--                      as the "pad".
  776. *--               11/09/1992 -- Joey Carroll added some minor changes 
  777. *--                      for cosmetics, as well as keeping the colors 
  778. *--                      working properly.
  779. *-- Calls.......: SHADOW               Procedure in PROC.PRG
  780. *--               CENTER               Procedure in PROC.PRG
  781. *--               JUSTIFY()            Function in WINDOWS.PRG
  782. *-- Called by...: Any
  783. *-- Usage.......: Alert2("<cTitle>","<cMessage>","<cColor>")
  784. *-- Example.....: lX = Alert2("Print Aborted","You pressed <ESC>",;
  785. *--                           "rg+/r,w+/b,rg+/r")
  786. *-- Returns.....: Logical
  787. *-- Parameters..: cTitle   = Title line
  788. *--               cMessage = One line message (up to 75 characters)
  789. *--               cColor   = Colors: <window forg/back>,<pad> (and 
  790. *--                                  title),<box>
  791. *-----------------------------------------------------------------------
  792.  
  793.    parameters cTitle, cMessage, cColor
  794.    private wWindow,nRow,nCol,mPad,cTempCol
  795.    
  796.    m->wWindow = WINDOW()               && save current Window
  797.    save screen to sTemp                && save the screen
  798.    i=inkey()                           && clear out keyboard buffer
  799.    
  800.    *-- get window coordinates
  801.    *-- this centers from top to bottom, depending on monitor setup ...
  802.    m->nULRow = iif(val(right(set("DISPLAY"),2)) = 43,18,8)
  803.    *-- add 6, so the Window is large enough ...
  804.    m->nBRRow = m->nULRow + 6
  805.    *-- left column ...
  806.    m->nULCol = 36 - (max(len(m->cTitle),len(m->cMessage))/2)    
  807.                                                   && center left-right
  808.    *-- right column ...
  809.    m->nBRCol = m->nULCol + max(len(m->cTitle),len(m->cMessage))+4  
  810.                                                   && right side
  811.    *-- Window width ...
  812.    m->nWidth = m->nBRCol - m->nULCol - 1
  813.    
  814.    *-- define window
  815.    Define window wAlert from m->nULRow,m->nULCol to m->nBRRow,m->nBRCol;
  816.                   DOUBLE color &cColor.
  817.    activate screen
  818.    *-- display shadow
  819.    do shadow with m->nULRow,m->nULCol,m->nBRRow,m->nBRCol
  820.    
  821.    *-- start 'er up ...
  822.    activate window wAlert
  823.    
  824.    *-- display title
  825.    m->cTempCol = colorbrk(m->cColor,2)
  826.    if len(m->cTitle) < m->nWidth
  827.       m->cTitle = justify(m->cTitle,m->nWidth,"C")
  828.       if len(m->cTitle) < m->nWidth
  829.          m->cTitle = m->cTitle + " "
  830.       endif
  831.    endif
  832.    do center with 0,m->nWidth,m->cTempCol,m->cTitle
  833.    
  834.    *-- display line 
  835.    m->cTempCol = colorbrk(m->cColor,1)
  836.    @1,0 say replicate(chr(196),m->nWidth) color &cTempCol.
  837.    
  838.    *-- display message
  839.    do center with 2,m->nWidth,"",m->cMessage
  840.    
  841.    *-- define/display a very small menu (one pad)
  842.    define menu mAlert
  843.    define pad pPad1 of mAlert prompt "[OK]" at 4,(m->nWidth/2)-1
  844.    on selection pad pPad1 of mAlert deactivate menu
  845.    
  846.    *-- added by Ken to deal with <Enter>
  847.    on key label ctrl-M keyboard "{27}"
  848.    
  849.    *-- start it up
  850.    activate menu mAlert
  851.    
  852.    *-- deal with user 'input'
  853.    m->mPad = pad()
  854.    release window wAlert
  855.    
  856.    *-- restore environment, free up RAM by releasing things
  857.    on key label ctrl-m
  858.    restore screen from sTemp
  859.    release screen sTemp
  860.    release menu mAlert
  861.    if "" # m->wWindow
  862.       activate window &wWindow.
  863.    endif
  864.    
  865. RETURN .not. "" = m->mPad  && not empty pad?
  866. *-- EoF: Alert2()
  867.  
  868. FUNCTION MsWind2
  869. *-----------------------------------------------------------------------
  870. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  871. *-- Date........: 06/23/1992
  872. *-- Notes.......: This one creates a window that acts like one from 
  873. *--               WINDOWS, in that you can move it, enlarge it to full-
  874. *--               screen, and bring it back to its original size.
  875. *--               NOTE: The Title is NOT displaying in the EXPANDED 
  876. *--               Window. This is based on a KNOWN BUG, forwarded to 
  877. *--               development.
  878. *-- Written for.: dBASE IV, 1.5
  879. *-- Rev. History: 06/23/1992 -- Ken Mayer -- Attempts made to use a 
  880. *--               'real' window (a dBASE defined window), shadows, 
  881. *--               colors, and make the window look more like a Microsoft
  882. *--               Windows Window.
  883. *-- Calls.......: MOVEWIN2             Procedure in WINDOWS.PRG
  884. *--               ENLARGE2             Procedure in WINDOWS.PRG
  885. *--               MSWINAC2             Procedure in WINDOWS.PRG
  886. *--               SHADOW               Procedure in PROC.PRG
  887. *-- Called by...: Any
  888. *-- Usage.......: MsWind2(<nTop>,<nLeft>,<nLower>,<nRight>,"<cColor>",;
  889. *--                      "<cTitle>")
  890. *-- Example.....: x=MsWind2(5,10,20,70,"rg+/gb,w+/b,rg+/gb",;
  891. *--                      "This is a title")
  892. *-- Returns.....: Logical
  893. *-- Parameters..: nTop    = Top Row of window
  894. *--               nLeft   = Left column
  895. *--               nBottom = Bottom Row of Window
  896. *--               nRight  = Right column
  897. *--               cColor  = Color combinations to be used:
  898. *--                         <Normal/Unselected pad>,<Selected pad>,<Box>
  899. *--               cTitle  = Title for first line of window ... 
  900. *--                         NOTE: if the title is longer than can be 
  901. *--                         displayed with the buttons on the first 
  902. *--                         line, it will be truncated ...
  903. *-----------------------------------------------------------------------
  904.  
  905.    parameters nTop, nLeft, nLower, nRight, cColor, cTitle
  906.    
  907.    *-- save environment
  908.    save screen to sMSWIND
  909.    m->lStatus = (set("STATUS") = "ON")
  910.    m->lDisp43 = ("43" $ SET("DISPLAY"))
  911.    
  912.    *-- loop
  913.    do while .t.
  914.    
  915.       *-- bring back old screen before defining all this
  916.       if window() = "WMSWIND"
  917.          deactivate window wMSWIND
  918.       endif
  919.       restore screen from sMSWIND
  920.    
  921.       *-- define/redefine window area and box
  922.       activate screen
  923.       define window wMSWind from m->nTop,m->nLeft to ;
  924.               m->nLower,m->nRight double color &cColor.
  925.       do shadow with m->nTop,m->nLeft,m->nLower,m->nRight
  926.       activate window wMSWind
  927.    
  928.       *-- deal with defining where to display the title (and truncating
  929.       *-- if necessary)
  930.       *-- define width and height of window
  931.       m->nWidth = m->nRight - m->nLeft - 2  && account for border
  932.       m->nHeight = m->nLower - m->nTop - 2  && ditto
  933.    
  934.       m->nWidth2 = m->nWidth - 9 && (space used by menu buttons)
  935.       if len(trim(m->cTitle)) > (m->nWidth2 - 2) 
  936.                               && leave room for a space on each sd
  937.          m->cTitle2 = left(m->cTitle,m->nWidth2-2)
  938.       else
  939.          m->cTitle2 = trim(m->cTitle)
  940.       endif
  941.       m->nSpaces = m->nWidth2 - len(m->cTitle2)
  942.       m->nSpaces1 = m->nSpaces/2
  943.       m->nSpaces2 = iif(m->nSpaces1=int(m->nSpaces/2),;
  944.                         m->nSpaces1,m->nSpaces1+1)
  945.       m->cTitle2 = space(m->nSpaces1) + m->cTitle2 + space(m->nSpaces2)
  946.       m->cTitlCol = colorbrk(m->cColor,2)
  947.       @0,3 say m->cTitle2 color &cTitlCol.
  948.    
  949.       *-- using menus to simulate Windows window ...
  950.       define menu wNormal
  951.       define pad pCabinet of wNormal prompt "["+chr(254)+"]" at 0, 0
  952.       define pad pMoveUp  of wNormal prompt "["+chr(24)+"]"  at 0,;
  953.                                                     m->nWidth - 6
  954.       define pad pEnlarge of wNormal prompt "["+chr(30)+"]" at 0,;
  955.                                                     m->nWidth - 3
  956.       define pad pMoveDn  of wNormal prompt "["+chr(25)+"]" ;
  957.                                      at m->nHeight, m->nWidth - 3
  958.       define pad pMoveRt  of wNormal prompt "["+chr(26)+"]" ;
  959.                                      at m->nHeight, m->nWidth - 6
  960.       define pad pMoveLf  of wNormal prompt "["+chr(27)+"]" ;
  961.                                      at m->nHeight, m->nWidth - 9
  962.    
  963.       *-- tell it what to do when an item is selected
  964.       on selection pad pCabinet of wNormal deactivate menu
  965.       on selection pad pMoveUp  of wNormal do movewin with pad()
  966.       on selection pad pEnlarge of wNormal do enlarge2 with m->cTitle,;
  967.                                                             m->cTitlCol
  968.       on selection pad pMoveDn  of wNormal do movewin with pad()
  969.       on selection pad pMoveRt  of wNormal do movewin with pad()
  970.       on selection pad pMoveLf  of wNormal do movewin with pad()
  971.    
  972.       *-- Display something in Window
  973.       do mswinat2
  974.    
  975.       *-- start the menu
  976.       activate menu wnormal
  977.    
  978.       *-- User pressed <Esc> or chose the 'close window' button/pad
  979.       if lastkey() = 27 .or. "PCABINET" = pad()
  980.          exit
  981.       endif
  982.    
  983.    enddo  && end of loop
  984.    
  985.    *-- restore environment
  986.    release window wMSWind
  987.    restore screen from sMSWIND
  988.    release screen sMSWIND
  989.    release menu wNormal
  990.    
  991. RETURN .not. "" = pad()
  992. *-- EoF: MSWind2()
  993.  
  994. PROCEDURE Enlarge2
  995. *-----------------------------------------------------------------------
  996. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  997. *-- Date........: 06/23/1992
  998. *-- Notes.......: Used in MSWIND2() to 'enlarge' the a window, and 
  999. *--               redfine the menu ...
  1000. *-- Written for.: dBASE IV, 1.5
  1001. *-- Rev. History: 06/23/1992 -- Ken Mayer (CIS: 71333,1030) - redefined
  1002. *--                 to handle using real dBASE Windows ...
  1003. *-- Calls.......: MsWinAt2             Procedure in WINDOWS.PRG
  1004. *-- Called by...: MsWind2()            Function in WINDOWS.PRG
  1005. *-- Usage.......: Do Enlarge2 with cTitle, cTitlCol
  1006. *-- Example.....: Do Enlarge2 with cTitle, cTitlCol
  1007. *-- Returns.....: None
  1008. *-- Parameters..: cTitle   = Title from MSWIND2()
  1009. *--               cTitlCol = Title color (also from MSWIND2())
  1010. *-----------------------------------------------------------------------
  1011.    
  1012.    parameters cTitle, cTitlCol
  1013.    
  1014.    *-- do a new version of the window ...
  1015.    deactivate window wMSWind
  1016.    restore screen from sMSWIND
  1017.    activate screen
  1018.    define window wMSWind from 0,0 to iif(m->lStatus,20,23) + ;
  1019.           iif(m->lDisp43,18,0), 77 double color &cColor.
  1020.    do shadow with 0,0,iif(lstatus,20,23)+iif(m->lDisp43,18,0),77
  1021.    activate window wMSWind
  1022.    
  1023.    *-- deal with TITLE ...
  1024.    *-- deal with defining where to display the title (and truncating
  1025.    *-- if necessary)
  1026.    *-- define width and height of window
  1027.    m->nWidth = 74 && account for border
  1028.    m->nWidth2 = m->nWidth - 6 && (space used by menu buttons)
  1029.    if len(trim(m->cTitle)) > (m->nWidth2 - 2) 
  1030.                                  && leave room for a space on each side
  1031.       m->cTitle2 = left(m->cTitle,m->nWidth2-2)
  1032.    else
  1033.       m->cTitle2 = trim(m->cTitle)
  1034.    endif
  1035.    m->nSpaces = m->nWidth2 - len(m->cTitle2)
  1036.    m->nSpaces1 = m->nSpaces/2
  1037.    m->nSpaces2 = iif(m->nSpaces1=int(m->nSpaces/2),m->nSpaces1,;
  1038.                                                    m->nSpaces1+1)
  1039.    m->cTitle2 = space(m->nSpaces1) + m->cTitle2 + space(m->nSpaces2)
  1040.    @0,3 say m->cTitle2 color &cTitlCol.
  1041.    
  1042.    *-- define new version of menu
  1043.    define menu mEnlarge
  1044.    define pad pCabinet of mEnlarge prompt "["+chr(254)+"]" at 0,0
  1045.    define pad pReduce  of mEnlarge prompt "["+chr(31)+"]"  at 0,72
  1046.    on selection pad pCabinet of mEnlarge deactivate menu
  1047.    on selection pad pReduce  of mEnlarge deactivate menu
  1048.    
  1049.    *-- Routine to allow interaction inside menu window ...
  1050.    do mswinat2
  1051.    
  1052.    *-- start 'er up
  1053.    activate menu mEnlarge
  1054.    if lastkey() = 27
  1055.       keyboard "{27}"
  1056.    endif
  1057.    deactivate menu
  1058.    release window wMSWIND
  1059.    release menu mEnlarge
  1060.  
  1061. RETURN
  1062. *-- EoP: Enlarge2
  1063.  
  1064. PROCEDURE MoveWin
  1065. *-----------------------------------------------------------------------
  1066. *-- Programmer..: Ken Mayer (CIS: 71333,1030)
  1067. *-- Date........: 06/23/1992
  1068. *-- Notes.......: Used in MSWIND() to move the window up (unless the
  1069. *--               window is at the top of the screen ...)
  1070. *-- Written for.: dBASE IV, 1.5
  1071. *-- Rev. History: 06/23/1992 -- Original
  1072. *-- Calls.......: None
  1073. *-- Called by...: MsWind()             Function in WINDOWS.PRG
  1074. *-- Usage.......: Do MoveWin with <pPad> 
  1075. *-- Example.....: Do MoveWin with pad()
  1076. *-- Returns.....: None
  1077. *-- Parameters..: pPad = menu pad selected to move window ...
  1078. *-----------------------------------------------------------------------
  1079.    
  1080.    parameters pPad
  1081.    
  1082.    restore screen from sMSWIND
  1083.    
  1084.    do case
  1085.       case m->pPad = "PMOVEUP"
  1086.    
  1087.          *-- check for top of screen ... change coordinates
  1088.          m->nTop = m->nTop - iif(m->nTop = 0,0,1)
  1089.          m->nLower = m->nLower - iif(m->nTop = 0,0,1)
  1090.    
  1091.       case m->pPad = "PMOVEDN"
  1092.    
  1093.          m->nTop = m->nTop + iif(m->nLower = iif(m->lStatus,21,24)+;
  1094.                   iif(m->lDisp43,18,0),0,1)
  1095.          m->nLower = m->nLower + iif(m->nLower=iif(m->lStatus,21,24)+;
  1096.                   iif(m->lDisp43,18,0),0,1)
  1097.    
  1098.       case m->pPad = "PMOVELF"
  1099.    
  1100.          m->nLeft = m->nLeft - iif(m->nLeft = 0,0,1)
  1101.          m->nRight = m->nRight - iif(m->nLeft = 0,0,1)
  1102.    
  1103.       case m->pPad = "PMOVERT"
  1104.    
  1105.          m->nRight = m->nRight + iif(m->nRight = 79,0,1)
  1106.          m->nLeft = m->nLeft + iif(m->nRight = 79,0,1)
  1107.    
  1108.    endcase
  1109.    deactivate menu
  1110.    
  1111. RETURN
  1112. *-- EoP: MoveWin
  1113.  
  1114. PROCEDURE MSWinAt2
  1115. *-----------------------------------------------------------------------
  1116. *-- Programmer..: Adam L. Menkes (BORLAND TECHNICAL SUPPORT)
  1117. *-- Date........: 06/23/1992
  1118. *-- Notes.......: Used in MSWIND2() to move the actually display/
  1119. *--               redisplay information inside the window, even when a 
  1120. *--               window has been moved. This routine should be 
  1121. *--               modified for a specific system ...  This version 
  1122. *--               (for MSWIND2()) starts counting at the top + 1 -- 
  1123. *--               the first line (0) is for the menu and the title ...
  1124. *-- Written for.: dBASE IV, 1.5
  1125. *-- Rev. History: 06/01/1992 -- Original
  1126. *--               06/23/1992 -- Modified by Ken Mayer to work with 
  1127. *--                             MSWIND2().
  1128. *-- Calls.......: None
  1129. *-- Called by...: MsWind2()            Function in WINDOWS.PRG
  1130. *-- Usage.......: Do MSWinAt2
  1131. *-- Example.....: Do MSWinAt2
  1132. *-- Returns.....: None
  1133. *-- Parameters..: None
  1134. *-----------------------------------------------------------------------
  1135.    
  1136.    @1,1 say "This is line 1"
  1137.    @2,1 say "And this is line 2"
  1138.    
  1139. RETURN
  1140. *-- EoP: MSWinAt2
  1141.  
  1142. FUNCTION Alert3
  1143. *-----------------------------------------------------------------------
  1144. *-- Programmer..: Adam L. Menkes (SUPREME1)
  1145. *-- Date........: 12/23/1992
  1146. *-- Notes.......: This function based on Alert2()
  1147. *--               This routine creates a popup on the screen with a 
  1148. *--               title and one line message, forcing the user to notice
  1149. *--               the message. The user must use the mouse on the 'OK' 
  1150. *--               pad, press <Esc> or press <Enter> to move on in the 
  1151. *--               program that called this function.
  1152. *-- Written for.: dBASE IV, 1.5
  1153. *-- Rev. History: Original: 06/19/1992
  1154. *--               Alert2()
  1155. *--               Modified to accept the <Enter> key by Ken Mayer.
  1156. *--               06/19/1992 -- Copied from Adam's original, uses a 
  1157. *--                 window, shadow, and programmer defineable colors.
  1158. *--               07/29/1992 -- Joey stepped in and made some 
  1159. *--                 modifications that seem to have helped as well, 
  1160. *--                 including dealing with the keyboard buffer.
  1161. *--               10/09/1992 -- minor change -- title is now same color 
  1162. *--                 as the "pad".
  1163. *--               Alert22()
  1164. *--               11/12/1992 -- changed to look more like a Win 3.0/3.1
  1165. *--                 window by printing a special 'line' below the title.
  1166. *--                 Also removed hard coding which forced border to 
  1167. *--                 DOUBLE so that if called with border set to NONE, 
  1168. *--                 gives even more Win-like appearance.  Calls a new 
  1169. *--                 function written for this technique, but can be used
  1170. *--                 in other programs.
  1171. *--               11/16/1992 -- modified to add cBORDER parameter ... 
  1172. *--                 (K. Mayer)
  1173. *--               12/23/1992 -- tuned up centering of cTitle, cMessage, 
  1174. *--                 and [OK] pad.  Eliminated calls to Center.prg by 
  1175. *--                 using Justify() along with @ say. (Joey Carroll)
  1176. *-- Calls.......: SHADOW               Procedure in PROC.PRG
  1177. *--               JUSTIFY()            Function in PROC.PRG
  1178. *--               COLORBRK()           Function in PROC.PRG
  1179. *--               FBCLRBRK()           Function in PROC.PRG 
  1180. *-- Called by...: Any
  1181. *-- Usage.......: Alert2("<cTitle>","<cMessage>","<cColor>"[,;
  1182. *--                         "<cBorder>"])
  1183. *-- Example.....: ** if no border, I suggest colors which will contrast
  1184. *--                  with the active screen or window
  1185. *--               lX = Alert2("Print Aborted","You pressed <ESC>",;
  1186. *--                           "rg+/r,w+/b,rg+/r","NONE")
  1187. *-- Returns.....: Logical
  1188. *-- Parameters..: cTitle   = Title line
  1189. *--               cMessage = One line message (up to 75 characters)
  1190. *--               cColor   = Colors: <window forg/back>,<pad> (and 
  1191. *--                          title),<box>
  1192. *--               cBorder  = Border type (DOUBLE, SINGLE, NONE, PANEL)  
  1193. *--                          optional -- will default to your setting
  1194. *-----------------------------------------------------------------------
  1195.  
  1196.    parameters cTitle, cMessage, cColor, cBorder
  1197.    private wWindow,mPad,cTempCol,cColorF,cColorB,cColorAll
  1198.    private nWidth,nULRow,nULCol,nLRRow,nLRCol,cTitle2,cMessage2,nBorder
  1199.  
  1200.    m->cTitle2 = " " + ltrim(trim(m->cTitle)) + " "      
  1201.                                            && don't jamb against walls
  1202.    m->cMessage2 = " " + ltrim(trim(m->cMessage)) + " "  
  1203.                                            && don't jamb against walls
  1204.    wWindow = WINDOW()                      && save current Window
  1205.    save screen to sTemp                    && save the screen
  1206.    activate screen
  1207.    m->cDummyKey = inkey()                  && clear out keyboard buffer
  1208.    m->cOldBorder = set("BORDER")           && get old border setting
  1209.    if .not. type("M->CBORDER") = "L"       && if user set border ...
  1210.       set border to &cBorder.              && start NEW border setting
  1211.    endif
  1212.    m->nBorder   = iif(set("BORDER") = "NONE",0,2)  && border factor
  1213.    *-- get window coordinates
  1214.    *-- this centers from top to bottom, depending on monitor setup ...
  1215.    m->nULRow = iif(val(right(set("DISPLAY"),2)) = 43,18,8)
  1216.    *-- add rows, number depends on border, so the Window is large 
  1217.    *-- enough ...
  1218.    m->nBRRow = m->nULRow + 5 +m->nBorder
  1219.  
  1220.    *-- left column ...
  1221.    m->nULCol = 40 - (max(len(m->cTitle2),len(m->cMessage2))/2)    
  1222.                                               && center left-right
  1223.    *-- right column ...
  1224.    m->nBRCol = m->nULCol + max(len(m->cTitle2),len(m->cMessage2));
  1225.                                                 + (m->nBorder - 1)
  1226.    *-- Window width ...
  1227.    m->nWidth = m->nBRCol - m->nULCol - 1
  1228.  
  1229.    *-- define window
  1230.    Define window wAlert from m->nULRow,m->nULCol to m->nBRRow,m->nBRCol;
  1231.                                                         color &cColor.
  1232.  
  1233.    *-- display shadow
  1234.    do shadow with m->nULRow,m->nULCol,m->nBRRow,m->nBRCol
  1235.  
  1236.    *-- start 'er up ...
  1237.    activate window wAlert
  1238.  
  1239.    *-- display  a new type type line to look more like Win
  1240.    m->cTempCol = colorbrk(m->cColor,2)
  1241.    m->cColorF   = FBClrBrk("B",m->cTempCol)           
  1242.                                         && background of title bar text
  1243.    m->cColorB   = FBClrBrk("B",colorbrk(m->cColor,1)) 
  1244.                                         && foreground of 'normal' text
  1245.    m->cColorAll = m->cColorF + "/" + m->cColorB 
  1246.                                         && color of 'special' line
  1247.    @ 0,0 say justify(m->cTitle2,m->nWidth +iif(m->nBorder = 0,4,2),"C");
  1248.                 color &cTempCol.        && the Title Bar
  1249.  
  1250.    *-- chr(223) looks like this --> fl <--
  1251.    @ 1,0 say replicate(chr(223),m->nWidth + 2) color &cColorAll.
  1252.                                          && make thicker
  1253.  
  1254.    *-- display message
  1255.    @ 2,0 say justify(m->cMessage2,m->nWidth + ;
  1256.                                      iif(m->nBorder = 0,4,2),"C")
  1257.    *-- define/display a very small menu (one pad)
  1258.    define menu mAlert
  1259.    define pad pPad1 of mAlert prompt "[OK]" at 4,;
  1260.                                       ((m->nWidth-m->nBorder-2)/2)
  1261.    on selection pad pPad1 of mAlert deactivate menu
  1262.  
  1263.    *-- added by Ken to deal with <Enter>
  1264.    on key label ctrl-M keyboard "{27}"
  1265.  
  1266.    *-- start it up
  1267.    activate menu mAlert
  1268.  
  1269.    *-- deal with user 'input'
  1270.    m->mPad = pad()
  1271.    release window wAlert
  1272.  
  1273.    *-- restore environment, free up RAM by releasing things
  1274.    on key label ctrl-m
  1275.    restore screen from sTemp
  1276.    release screen sTemp
  1277.    release menu mAlert
  1278.    if "" # m->wWindow
  1279.       activate window &wWindow.
  1280.    endif
  1281.    set border to &cOldBorder.
  1282.    
  1283. RETURN .not. "" = m->mPad  && not empty pad?
  1284. *-- EoF: Alert3()
  1285.  
  1286. FUNCTION YesNo3
  1287. *-----------------------------------------------------------------------
  1288. *-- Programmer..: Kenneth J. Mayer (CIS: 71333,1030)
  1289. *-- Date........: 01/06/1993
  1290. *-- Notes.......: A version of the YESNO() routines in PROC.PRG, that 
  1291. *--               will handle a long (up to 254 character) message 
  1292. *--               string, is centered on the screen, and has a title 
  1293. *--               bar kind of like a Windows dialog box ...
  1294. *-- Written for.: dBASE IV, 1.5
  1295. *-- Rev. History: 01/06/1993 -- Original
  1296. *-- Calls.......: Center               Procedure in PROC.PRG
  1297. *--               Shadow               Procedure in PROC.PRG
  1298. *--               WordWrap             Procedure in STRINGS.PRG
  1299. *--               ColorBrk()           Function in PROC.PRG
  1300. *--               FBClrBrk()           Function in PROC.PRG
  1301. *--               Justify()            Function in PROC.PRG
  1302. *-- Called by...: Any
  1303. *-- Usage.......: YesNo3(<lDefault>,<cTitle>,<cMessage>,<cColor>)
  1304. *-- Example.....: if YesNo3(.t.,"Test",;
  1305. *--                         "This is a message of any length"+;
  1306. *--                         "up to 254 characters.",cWind1)
  1307. *-- Returns.....: logical
  1308. *-- Parameters..: lDefault  = Logical value, for the default menu pad
  1309. *--                           (Yes/No)
  1310. *--               cTitle    = Title for title bar -- no longer than 30 
  1311. *--                           characters.
  1312. *--               cMessage  = Message - up to 254 characters in length.
  1313. *--               cColor    = "Standard" colors for window/menu/box
  1314. *-----------------------------------------------------------------------
  1315.  
  1316.    parameters lDefault, cTitle, cMessage, cColor
  1317.    private nULRow, nULCol, nBRRow, nBRCol, nLMargin, nRMargin, lWrap
  1318.    
  1319.    *-- save it, so we can activate the screen and display a window on top
  1320.    *-- of whatever's there
  1321.    save screen to sYesNo
  1322.    
  1323.    *-- save window if there is one, and activate screen to be safe:
  1324.    m->wWindow = window()
  1325.    activate screen
  1326.    
  1327.    *-- now to define the coordinates ...
  1328.    m->nULCol = 20   && left side of box
  1329.    m->nBRCol = 60   && right side of box
  1330.    
  1331.    m->nWidth =  36  && width of dialog box ... 36 characters for text
  1332.    m->nHeight = int(len(m->cMessage)/m->nWidth)
  1333.    *-- if the remainder of the length of the message/width of box is > 0
  1334.    *-- we have one more line of text ...
  1335.    m->nHeight = m->nHeight + iif(mod(len(m->cMessage),m->nWidth)>0,1,0)  
  1336.    
  1337.    *-- deal with room for title, and menu at bottom
  1338.    m->nHeight = m->nHeight + 4
  1339.    
  1340.    *-- row coordinates
  1341.    m->nULRow = (24-m->nHeight) / 2     && top row
  1342.    m->nBRRow = m->nULRow + m->nHeight + 1
  1343.    
  1344.    *-- define the window
  1345.    define window wYesNo from m->nULRow,m->nULCol to m->nBRRow,m->nBRCol;
  1346.                                   double color &cColor.
  1347.    
  1348.    *-- now for the menu pads
  1349.    define menu mYesNo
  1350.    define pad pYes of mYesNo prompt "[Yes]" at m->nHeight - 1,10
  1351.    define pad pNo  of mYesNo prompt "[No]"  at m->nHeight - 1,25
  1352.    on selection pad pYes of mYesNo deactivate menu
  1353.    on selection pad pNo  of mYesNo deactivate menu
  1354.    
  1355.    *-- display it
  1356.    do shadow with m->nULRow,m->nULCol,m->nBRRow,m->nBRCol
  1357.    activate window wYesNo
  1358.    
  1359.    *-- display title
  1360.    if len(m->cTitle) < m->nWidth
  1361.       m->cTitle = justify(m->cTitle,39,"C")
  1362.       if len(m->cTitle) < 39
  1363.          m->cTitle = m->cTitle + " "
  1364.       endif
  1365.    endif
  1366.    m->cTempCol = colorbrk(m->cColor,2)
  1367.    m->cColorF  = FBClrBrk("B",m->cTempCol)
  1368.    m->cColorB  = FBClrBrk("B",colorbrk(m->cColor,1))
  1369.    m->cColorAll = m->cColorF + "/" + m->cColorB
  1370.    @0,0 say m->cTitle color &cTempCol.
  1371.    @1,0 say replicate(chr(223),39) color &cColorAll.
  1372.    
  1373.    *-- display message
  1374.    do WordWrap with 2,2,m->cMessage,35
  1375.    
  1376.    *-- set Y/N keys for menu pad
  1377.    clear typeahead && just to be safe
  1378.    on key label Y keyboard iif(pad() = "PYES","",chr(19))+chr(13)
  1379.    on key label N keyboard iif(pad() = "PNO", "",chr(4) )+chr(13)
  1380.    
  1381.    *-- activate the menu
  1382.    if m->lDefault
  1383.       activate menu mYesNo pad pYes
  1384.    else
  1385.       activate menu mYesNo pad pNo
  1386.    endif
  1387.    
  1388.    *-- reset system
  1389.    on key label Y
  1390.    on key label N
  1391.    release window wYesNo
  1392.    restore screen from sYesNo
  1393.    release screen sYesNo
  1394.    release menu mYesNo
  1395.    if .not. isblank(m->wWindow)
  1396.       activate window &wWindow.
  1397.    endif
  1398.  
  1399. RETURN iif(pad() = "PYES",.t.,.f.)
  1400. *-- EoF: YesNo3()
  1401.  
  1402. *-----------------------------------------------------------------------
  1403. *-- These functions are here so that we don't have to go hunting all 
  1404. *-- over
  1405. *-----------------------------------------------------------------------
  1406.  
  1407. FUNCTION TempName
  1408. *-----------------------------------------------------------------------
  1409. *-- Programmer..: Martin Leon (HMAN)  Former Sysop, ATBBS
  1410. *-- Date........: 05/27/1992
  1411. *-- Notes.......: Obtain a name for a temporary file of a given 
  1412. *--               extension that does not conflict with existing files.
  1413. *-- Written for.: dBASE IV, v1.5
  1414. *-- Rev. History: Originally part of Makestru(), 6-12-1991
  1415. *--               04/26/92, made a separate function - Jay Parsons
  1416. *--               05/27/92, added lDBTMP option - Bowen Moursund
  1417. *-- Calls.......: None
  1418. *-- Called by...: Any
  1419. *-- Usage.......: TempName( cExt , lDBTMP )
  1420. *-- Example.....: Sortfile = TempName( "DBF" , .t. )
  1421. *-- Returns.....: Name not already in use. Additionally, if the memvar
  1422. *--               cDBTMP is declared before calling the function with
  1423. *--               the lDBTMP option, it will be assigned the result
  1424. *--               of getenv("DBTMP").
  1425. *-- Parameters..: cExt   = Extension to be given file ( without the ".")
  1426. *--               lDBTMP = Optional. If .t., function returns unique 
  1427. *--                        file name in the DBTMP subdirectory.
  1428. *-- Side Effects: The function will return a unique filename for the 
  1429. *--               DEFAULT subdirectory if the lDBTMP option is used and 
  1430. *--               the DOS environment variable DBTMP does not point to 
  1431. *--               a valid subdirectory.
  1432. *-----------------------------------------------------------------------
  1433.  
  1434.    parameters cExt, lDBTMP
  1435.    private all except cDBTMP
  1436.    m->cDefDir = set("DIRECTORY")
  1437.    if m->lDBTMP
  1438.       m->cDBTMP = getenv("DBTMP")
  1439.       if "" # m->cDBTMP
  1440.          set directory to &cDBTMP.
  1441.       endif
  1442.    endif
  1443.    do while .t.
  1444.       m->fName = "TMP" + ltrim( str( rand() * 100000, 5 ) )
  1445.       if .not. file( m->fName + "." + m->cExt ) .and.;
  1446.          ( upper( m->cExt ) # "DBF" .or.;
  1447.           .not. ( file( m->fName + ".MDX" ) .or. file ;
  1448.           ( m->fName + ".DBT" ) ) )
  1449.          exit
  1450.       endif
  1451.    enddo
  1452.    set directory to &cDefDir.
  1453.  
  1454. RETURN m->fName
  1455. *-- Eof() TempName
  1456.  
  1457. FUNCTION ArrayRows
  1458. *-----------------------------------------------------------------------
  1459. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  1460. *-- Date........: 03/01/1992
  1461. *-- Notes.......: Number of Rows in an array
  1462. *-- Written for.: dBASE IV, 1.1
  1463. *-- Rev. History: 03/01/1992 -- Original
  1464. *-- Calls.......: None
  1465. *-- Called by...: Any
  1466. *-- Usage.......: ArrayRows("<aArray>")
  1467. *-- Example.....: n = ArrayRows("aTest")
  1468. *-- Returns.....: numeric
  1469. *-- Parameters..: aArray      = Name of array 
  1470. *-----------------------------------------------------------------------
  1471.  
  1472.    parameters aArray
  1473.    private nHi, nLo, nTrial, nDims
  1474.    m->nLo = 1
  1475.    m->nHi = 1170
  1476.    if type( "&aArray.[ 1, 1 ]" ) = "U"
  1477.       m->nDims = 1
  1478.    else
  1479.       m->nDims = 2
  1480.    endif
  1481.    do while .T.
  1482.       m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
  1483.       if m->nHi < m->nLo
  1484.          exit
  1485.       endif
  1486.       if m->nDims = 1 .and. type( "&aArray.[ m->nTrial ]" ) = "U" .or. ;
  1487.          m->nDims = 2 .and. type( "&aArray.[ m->nTrial, 1 ]" ) = "U"
  1488.          m->nHi = m->nTrial - 1
  1489.      else
  1490.          m->nLo = m->nTrial + 1
  1491.      endif
  1492.    enddo
  1493.    
  1494. RETURN m->nTrial
  1495. *-- EoF: ArrayRows()
  1496.  
  1497. FUNCTION ArrayCols
  1498. *-----------------------------------------------------------------------
  1499. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  1500. *-- Date........: 03/01/1992
  1501. *-- Notes.......: Number of Columns in an array
  1502. *-- Written for.: dBASE IV, 1.1
  1503. *-- Rev. History: 03/01/1992 -- Original
  1504. *-- Calls.......: None
  1505. *-- Called by...: Any
  1506. *-- Usage.......: ArrayCols("<aArray>")
  1507. *-- Example.....: n = ArrayCols("aTest")
  1508. *-- Returns.....: numeric
  1509. *-- Parameters..: aArray      = Name of array 
  1510. *-----------------------------------------------------------------------
  1511.  
  1512.    parameters aArray
  1513.         private nHi, nLo, nTrial
  1514.    m->nLo = 1
  1515.    m->nHi = 1170
  1516.    if type( "&aArray.[ 1, 1 ]" ) = "U"
  1517.       RETURN 0
  1518.    endif
  1519.    do while .t.
  1520.       m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
  1521.       if m->nHi < m->nLo
  1522.          exit
  1523.       endif
  1524.       if type( "&aArray.[ 1, m->nTrial ]" ) = "U"
  1525.          m->nHi = m->nTrial - 1
  1526.       else
  1527.          m->nLo = m->nTrial + 1
  1528.       endif
  1529.    enddo
  1530.  
  1531. RETURN m->nTrial
  1532. *-- EoF: ArrayCol()
  1533.  
  1534. FUNCTION FieldNum
  1535. *-----------------------------------------------------------------------
  1536. *-- Programmer..: ?
  1537. *-- Date........: 03/09/1992
  1538. *-- Notes.......: Designed to return the number of a given fieldname in 
  1539. *--               the database structure. Works on open database only.
  1540. *-- Written for.: dBASE IV, 1.5
  1541. *-- Rev. History: 06/01/1992 -- Adam L. Menkes for 1.5 ...
  1542. *-- Calls.......: None
  1543. *-- Called by...: Any
  1544. *-- Usage.......: FieldNum("<cFldName>")
  1545. *-- Example.....: n = FieldNum("Firstname")
  1546. *-- Returns.....: Numeric
  1547. *-- Parameters..: cFldName = Name of Field 
  1548. *-----------------------------------------------------------------------
  1549.  
  1550.    Parameters cFldName
  1551.    m->cExact = set("EXACT")
  1552.    set exact on
  1553.    m->nField = 1
  1554.    do while upper(m->cFldName) <> FIELD(m->nField) .and. ;
  1555.       m->nField <= fldcount()
  1556.       m->nField = m->nField + 1
  1557.    enddo
  1558.    set exact &cExact.
  1559.  
  1560. RETURN iif(len(trim(field(m->nField))) = 0,0,m->nField)
  1561. *-- EoF: FieldNum()
  1562.  
  1563. FUNCTION Justify
  1564. *-----------------------------------------------------------------------
  1565. *-- Programmer..: Roland Bouchereau (Ashton-Tate)
  1566. *-- Date........: 12/23/1992
  1567. *-- Notes.......: Used to pad a field/string on the right, left or both,
  1568. *--               justifying or centering it within the length 
  1569. *--               specified. If the length of the string passed is 
  1570. *--               greater than the size needed, the function will 
  1571. *--               truncate it.
  1572. *--               Taken from Technotes, June 1990. Defaults to Left 
  1573. *--               Justify if invalid TYPE is passed ...
  1574. *-- Written for.: dBASE IV, 1.0
  1575. *-- Rev. History: Original function 06/15/1991
  1576. *--               12/17/1991 -- Modified into ONE function from three by
  1577. *--                  Ken Mayer, added a third parameter to handle that.
  1578. *--               12/23/1992 -- Modified by Joey Carroll to use STUFF()
  1579. *--                  instead of TRANSFORM().
  1580. *-- Calls.......: None
  1581. *-- Called by...: Any
  1582. *-- Usage.......: Justify(<cFld>,<nLength>,"<cType>")
  1583. *-- Example.....: ?? Justify(Address,25,"R")
  1584. *-- Returns.....: Padded/truncated field
  1585. *-- Parameters..: cFld    =  Field/Memvar/Character String to justify
  1586. *--               nLength =  Width to justify within
  1587. *--               cType   =  Type of justification: L=Left, C=Center,
  1588. *--                          R=Right
  1589. *-----------------------------------------------------------------------
  1590.    
  1591.    parameters cFld,nLength,cType
  1592.    private cReturn
  1593.    
  1594.    m->cType = upper(m->cType)    && just making sure ...
  1595.    if type("m->cFld")+type("m->nLength")+type("m->cType") $ "CNC,CFC"
  1596.       *-- set a picture function of 'X's, with @I,@J or @B function
  1597.       m->cReturn = space(m->nLength)
  1598.       m->cReturn = stuff(m->cReturn,;
  1599.                    iif(m->cType = "C",(m->nLength-len(m->cFld))/2,;
  1600.                    iif(m->cType = "R",m->nLength-len(m->cFld)+1,1)),;
  1601.                    len(m->cFld),m->cFld)
  1602.    else
  1603.       m->cReturn = ""
  1604.    endif
  1605.  
  1606. RETURN m->cReturn
  1607. *-- EoF: Justify()
  1608.  
  1609. PROCEDURE WordWrap
  1610. *-----------------------------------------------------------------------
  1611. *-- Programmer..: David Frankenbach (CIS: 72147,2635)
  1612. *-- Date........: 01/14/1993 (Version 1.1)
  1613. *-- Notes.......: Wraps a long string, breaking it into strings that 
  1614. *--               have a maximum length of nWidth. The first output is 
  1615. *--               displayed @nRow, nCol. Words are not split ...
  1616. *-- Written for.: dBASE IV, 1.5
  1617. *-- Rev. History: 01/06/1993 -- Original Release (Version 1.0)
  1618. *--               01/14/1993 -- Version 1.1 -- Corrected side-effect of 
  1619. *--                       destroying string arg, added test for 
  1620. *--                       string[nWidth+1] = " "
  1621. *-- Calls.......: None
  1622. *-- Called by...: Any
  1623. *-- Usage.......: do WordWrap with <nRow>, <nCol>, <cString>, <nWidth>
  1624. *-- Example.....: do WordWrap with 2,2,cText,38
  1625. *-- Returns.....: None
  1626. *-- Parameters..: nRow     = Row to display first line at
  1627. *--               nCol     = Left side of area to display text at
  1628. *--               cString  = text to wrap
  1629. *--               nWidth   = Width of area to wrap text in
  1630. *-----------------------------------------------------------------------
  1631.  
  1632.    parameters nRow, nCol, cString, nWidth
  1633.    private cTemp, nI, cStr
  1634.    
  1635.    m->cStr = m->cString            && work with a COPY of input, to 
  1636.                                    && avoid destroying original
  1637.    
  1638.    do while len(m->cStr) > 0       && while there's something to work on
  1639.       if (m->nWidth < len(m->cStr))
  1640.          m->nI = m->nWidth         && look for last " " in first nWidth
  1641.    
  1642.          if substr(m->cStr,m->nI+1,1) # " "
  1643.        do while ( (m->nI > 0) .and.;
  1644.           (substr(m->cStr,m->nI,1) # " "))
  1645.                m->nI = m->nI - 1
  1646.             enddo
  1647.          endif
  1648.    
  1649.          if m->nI = 0                && no spaces
  1650.             m->nI = m->nWidth        && get first nWidth characters
  1651.         endif
  1652.       else
  1653.          m->nI = len(m->cStr)        && use the rest of the string
  1654.       endif
  1655.    
  1656.       m->cTemp = left(m->cStr,m->nI) && get the part we're going to 
  1657.                                      && display
  1658.    
  1659.       if m->nI < len(m->cStr)        && remove that part
  1660.          m->cStr = ltrim(substr(m->cStr,m->nI + 1))
  1661.       else
  1662.          m->cStr = ""
  1663.       endif
  1664.    
  1665.       *-- display it
  1666.       @m->nRow,m->nCol say m->cTemp
  1667.       *-- move to next row
  1668.       m->nRow = m->nRow + 1
  1669.    
  1670.    enddo
  1671.    
  1672. RETURN
  1673. *-- EoP: WordWrap
  1674.  
  1675. *-----------------------------------------------------------------------
  1676. *-- End of Program: WINDOWS.PRG
  1677. *-----------------------------------------------------------------------
  1678.